package com.itheima.es;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * sort排序
 * from+size分页
 * @作者 itcast
 * @创建日期 2020/11/29 9:31
 **/
public class EsDemo05 {
    RestHighLevelClient restHighLevelClient;

    /**
     * 查询所有数据
     * 1. 先按照性别进行分桶
     * 2. 求出每个分桶下年龄的平均值
     */
    @Test
    public void aggregations() throws IOException {
        // 1. 创建搜索请求
        SearchRequest request = new SearchRequest("user");
        // 构建请求参数
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 聚合条件的构建 使用工具类 AggregationBuilders
        // 参数: 自定义的聚合名称
        // 构建一个分桶的聚合条件
        TermsAggregationBuilder termsBuilder = AggregationBuilders.terms("terms_by_gender").field("gender");
        // 构建一个求平均值的聚合条件
        AvgAggregationBuilder avgBuilder = AggregationBuilders.avg("avg_by_age").field("age");
        // 将求平均值的聚合条件设置到分桶的子聚合   先分桶在求每个分桶的平均年龄
        termsBuilder.subAggregation(avgBuilder);
        builder.aggregation(termsBuilder);
        request.source(builder);
        // 2. 执行搜索请求
        SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        // 总的聚合结果
        Aggregations aggregations = searchResponse.getAggregations();
        // 根据自定义的聚合名称 得到对应的结果
        Terms termsResult = aggregations.get("terms_by_gender");
        // 得到分桶信息
        List<? extends Terms.Bucket> buckets = termsResult.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            System.out.println("当前分桶的key: " + bucket.getKeyAsString());
            System.out.println("当前分桶的数量: " + bucket.getDocCount());
            // 获取子聚合的总结果
            Aggregations subAggs = bucket.getAggregations();
            // 获取该分桶下 请求平均值结果
            Avg avgResult = subAggs.get("avg_by_age");
            System.out.println("当前分桶的年龄平均值: " + avgResult.getValue());
        }
    }



    /**
     * note: match   查询 唱歌javaee
     *
     * 希望: note能够高亮显示  显示红色
     */
    @Test
    public void highlight() throws IOException {
        // 1. 创建搜索请求
        SearchRequest request = new SearchRequest("user");
        // 构建请求参数
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.matchQuery("note","唱歌javaee"));
        // 构建高亮条件
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("note");// 设置高亮字段
        highlightBuilder.preTags("<span style='color:red'>");// 前置标签
        highlightBuilder.postTags("</span>");// 前置标签
        builder.highlighter(highlightBuilder);
        // 将builer设置到request中
        request.source(builder);
        // 2. 执行搜索请求
        SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        // 3. 解析响应结果
        SearchHits hits = searchResponse.getHits();
        System.out.println("查询结果数量: " + hits.getTotalHits().value);

        SearchHit[] docList = hits.getHits();
        for (SearchHit searchHit : docList) {
            String userJson = searchHit.getSourceAsString();
            User user = JSON.parseObject(userJson,User.class);
            // 获取高亮的结果 ，设置到user.setNote(高亮结果);
            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            // 得到note字段所对应的高亮结果
            HighlightField highlightField = highlightFields.get("note");
            // 获取高亮的片段数组
            Text[] fragments = highlightField.getFragments();
            // 将所有高亮的片段拼接到一个字符串上，得到完成高亮结果
//            String str = StringUtils.join(fragments);
            StringBuilder sb = new StringBuilder();
            for (Text fragment : fragments) {
                sb.append(fragment);
            }
            // 将高亮的处理结果设置到user的note字段中
            user.setNote(sb.toString());
            System.out.println(user);
        }

    }



    @Before
    public void init(){
        restHighLevelClient = new RestHighLevelClient(
                RestClient.builder(
                        // 要连接的es地址
                        new HttpHost("192.168.200.150",9200,"http")
//                        new HttpHost("192.168.200.151",9200,"http"),   // 如果是集群的话可以写多个
//                        new HttpHost("192.168.200.152",9200,"http")
                )
        );
    }
    @After
    public void close() throws IOException {
        restHighLevelClient.close();
    }
}
